<template>
  <div class="webpack-sourcemap-test-event" style="overflow:auto">
    <h1>{{ message }}</h1>
    <section>
        <h3>一、什么是sourcemap</h3>
        <p>sourcemap可以认为是一个信息文件，它存储着转换前和转换后的文件内容的对应关系。可以让我们在调试压缩后的文件时很容易定位到源文件所对应代码的位置。</p>
    </section>
    <section>
        <h3>二、文件格式以及生成方式</h3>
        <code>
            <pre>
            {
                version : 3, // source map 的版本 现在一般为3
                file: "out.js", // 转换后的文件名
                sourceRoot : "", // 转换前的文件所在的目录。如果与转换前的文件在同一目录，该项为空。
                sources: ["foo.js", "bar.js"], // 转换前的文件。该项是一个数组，表示可能存在多个文件合并。
                names: ["src", "maps", "are", "fun"], // 转换前的所有变量名和属性名
                mappings: "AAgBC,SAAQ,CAAEA" // 记录位置信息的字符串
            }
            </pre>
        </code>
        <p>生成方式：首先安装uglify-js，之后在终端输入命令： uglifyjs 输入文件名 -o 输出文件名 --source-map -c -m</p>
    </section>
    <section>
        <h3>三、mappings</h3>
        <p>里面记录了转换前后对应文件对应位置的详细信息。内面大致分为三层</p>
        <ol>
            <li>第一层以分号（;）隔开，每一组代表转换后的一行</li>
            <li>第二层以逗号（,）隔开，每一组代表转换后源码的一个位置</li>
            <li>第三层是对应的位置转换，以<a href="https://en.wikipedia.org/wiki/Variable-length_quantity">VLQ</a>表示，代表源码的位置。</li>
        </ol>
        <p>例如以下信息</p>
        <code>
            <pre>
                mappings: "AAgBC,SAAQ;CAAEA"
            </pre>
        </code>
        <p>表示转换后会生成两行代码，第一行有两个位置，第二行只有一个位置。</p>
    </section>
    <section>
        <h3>四、编码原理</h3>
        <p>每个段由1、4或5位可变长度字段组成，(一位不一定对应对一个字符，下文将会讲到)，对应位置位</p>
        <ol>
            <li>输出文件第几列</li>
            <li>输入文件，对应sources中的第几个</li>
            <li>输入文件第几行</li>
            <li>输入文件第几列</li>
            <li>对应names中的第几个</li>
        </ol>
        <p>例如以下的mappings,在VLQ中A表示0位置，（下文讲怎么换算的）</p>
        <img class="img-shadow" src="../../images/webpack/mapping.jpeg">
    </section>
    <section>
        <h3>五、VLQ编码，以base64 VLQ为例</h3>
        <p>呈上base64编码字符表</p>
        <img class="img-shadow" src="../../images/webpack/base64.png" style="max-width: 500px">
        <p>以324这个位置为例</p>
        <table>
            <tr>
                <td width="100px">第一步转换为二进制</td>
                <td>324 =&gt; 101000100 </td>
            </tr>
            <tr>
                <td width="100px">第二步在最后面补位，整数补0，负数补1</td>
                <td>101000100 =&gt; 1010001000 </td>
            </tr>
            <tr>
                <td width="100px">第三步，从后向前每五个分一组，不够五个向前补0</td>
                <td>1010001000 =&gt; 10100 01000 </td>
            </tr>
            <tr>
                <td width="100px">第四步，位置反转，若前面全是0则省略此步</td>
                <td>10100 01000 =&gt; 01000 10100 </td>
            </tr>
            <tr>
                <td width="100px">第五步，从左往右每一组和后面连续的话在该组最前面补1，不连续补0或者省略</td>
                <td>01000 10100 =&gt; 101000 10100 </td>
            </tr>
            <tr>
                <td width="100px">第六步，按组转换为十进制</td>
                <td>101000 10100 =&gt; 40 20 </td>
            </tr>
            <tr>
                <td width="100px">第七步，每组的值对应base64字符表</td>
                <td>40 20 =&gt; o U </td>
            </tr>
        </table>
        <p>324 的编码结果为 oU</p>
        <p>自己可以尝试计算一下，可以通过以下地址验证结果<a href="http://murzwin.com/base64vlq.html">http://murzwin.com/base64vlq.html</a></p>
    </section>
    <section>
        <h3>六、位置关联计算</h3>
        <code>
            <pre>
                // 源文件
                var abc = 'daihaiqing234';

                var def = 'test';

                //  转换后文件
                var abc="daihaiqing234",def="test";

                // map 文件
                {
                    "version":3,
                    "sources":["main.js"],
                    "names":["abc","def"],
                    "mappings":"AAAA,IAAIA,IAAM,gBAENC,IAAM"
                }
            </pre>
        </code>
        <p>上面我们了解到怎么把位置对应成VLQ，那这个位置又是怎么计算出来的呢？</p>
        <p>我们来看一下 IAAIA 这个组，对应的编码是 [4,0,0,4,0],(为了减小每一组的长度，只有第一组是相对原文件的绝对位置，之后每一组都是相对前一个的相对位置。)</p>
        <p>我们先看着一组的最后一位A，是0，说明该组描述的是 abc 这个变量，他在输出文件的第4列对应第一个4，属于main.js，对应第一个0，在输入文件的第0行，对应第二个0，它相对上一个AAAA（0，0，0，0）位置往后偏移了4，对应第二个4。哈哈😁全中。</p>
        <p>我们刚才说到每一组有五位，但不一定只有五个字符，可以注意到有一个gBAENC他就是六位，我们开看看有什么特殊的。</p>
        <p>g 对应 VLQ 是32，转成二进制位 100000，首位是1 符合我们的第五步，补位连续位，他是1 说明是连续的，说明 gB 这两个占一位。也符合我们的规则。</p>
        <p>空格也会计算到移动位</p>
    </section>
    <p>根据自己的理解总结，有什么问题望大家斧正。</p>
    <p class="page-end">The End</p>
  </div>
</template>

<script lang="ts">
    import Vue from 'vue';
    import Component from 'vue-class-component';

    @Component({
        // 所有的组件选项都可以放在这里
    })
    export default class sourcemap extends Vue {
        // data 在这
        message: string = 'sourcemap'

    }
</script>
<style lang="scss">
.webpack-sourcemap-test-event{
}
</style>